package com.example.wac.component;

import cn.hutool.core.util.RandomUtil;
import com.example.wac.constant.Constant;
import com.example.wac.enums.ErrorCode;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.concurrent.TimeUnit;

/**
 * @author wuancheng
 * @description
 * @date 2023-05-31 15:37:00
 */

@Component
public class RedisHelper {
    @Resource(name = "atomicDeleteRedisScript")
    private RedisScript<Integer> atomicDeleteRedisScript;

    @Resource(name = "currentLimiterScript")
    private RedisScript<Long> currentLimiterScript;

    @Resource
    private RedisTemplate redisTemplate;

    public static String IP;

    /**
     * 单位时间最大次数
     */
    public static final int MAX_COUNT = 5;

    public RedisHelper(){
        try {
            IP = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 原子操作，删除key
     *
     * @param key
     * @param value
     * @return
     */
    public boolean isDelete(String key, String value){
        if (StringUtils.isAnyBlank(key, value)) {
            throw ErrorCode.PARAM_CANNOT_EMPTY.getAppException("key和value");
        }
        Integer result = (Integer) redisTemplate.execute(atomicDeleteRedisScript, Collections.singletonList(key), value);
        return result > 0;
    }

    /**
     * 原子操作，限流访问是否允许通过
     *
     * @param path
     * @return
     */
    public boolean isAllow(String path){
        if (StringUtils.isBlank(path)) {
            throw ErrorCode.PARAM_CANNOT_EMPTY.getAppException("接口路径");
        }
        String key = Constant.PREFIX + "currentLimit:" + path;
        long now = System.currentTimeMillis();
        long windowTimeMillis = TimeUnit.SECONDS.toMillis(60);
        String value = IP + "_" + now + "_" + RandomUtil.randomNumbers(10);
        Long result = (Long) redisTemplate.execute(currentLimiterScript, Collections.singletonList(key), now, windowTimeMillis, MAX_COUNT, now - windowTimeMillis, value);
        return result == 200;
    }
}
